# -*- coding: UTF-8 -*-
"""
 * @author  cyb233
 * @date  2021/4/18
"""
import base64
import hashlib
import hmac
import json
import logging
import time
import urllib.parse

import requests
import telebot
from urllib3.exceptions import InsecureRequestWarning

requests.urllib3.disable_warnings(InsecureRequestWarning)

_MAX_TRIES = 5
is_sign = 'https://api1.mimikko.cn/client/user/GetUserSignedInformation'  # 今天是否签到


def mimikko_login(url, app_id, app_Version, params, cache_server):      # 带尝试的登录post
    if cache_server:
        logging.info("尝试使用cache登录")
        cacheLogin_return = mimikko_cacheLogin(
            url, app_id, app_Version, params, cache_server)
        if cacheLogin_return:
            return cacheLogin_return

    return_value = False
    i = 1
    while True:
        logging.debug(f"第{i}次尝试登录")
        return_value = mimikko_realLogin(url, app_id, app_Version, params)
        if return_value != False:
            logging.debug("SUCCESS")
            break
        if i == _MAX_TRIES:
            logging.warning(f"{_MAX_TRIES}次请求失败，已跳过")
            break
        i = i + 1

    if cache_server and return_value:
        data = {
            'Accept': 'application/json',
            'Cache-Control': 'no-cache',
            'Host': cache_server,
            'Accept-Encoding': 'gzip',
            'User-Agent': 'okhttp/3.12.1',
            'User-Id': hashlib.sha256(params["id"].encode('utf-8')).hexdigest(),
            'User-Pass': params["password"],
            "value": return_value,
        }
        requests.post(cache_server, data=json.dumps(data), timeout=300)

    return return_value


def mimikko_cacheLogin(url, app_id, app_Version, params, cache_server):  # 尝试使用cache登录
    if cache_server:
        try:
            headers = {
                'Accept': 'application/json',
                'Cache-Control': 'no-cache',
                'Host': cache_server,
                'Accept-Encoding': 'gzip',
                'User-Agent': 'okhttp/3.12.1',
                'User-Id': hashlib.sha256(params["id"].encode('utf-8')).hexdigest(),
                'User-Pass': params["password"],
            }
            with requests.get(cache_server, headers=headers, timeout=300) as resp:
                res = resp.json()
                if res["success"]:
                    test = mimikko_realGet(
                        is_sign, app_id, app_Version, res["value"]["body"]["Token"], "")
                    if test["code"] != "0":
                        return False
                    return res["value"]
                else:
                    return False
        except Exception as exl:
            logging.error(exl, exc_info=True)
            return False


def mimikko_realLogin(url, app_id, app_Version, params):  # 实际登录post
    headers = {
        'Accept': 'application/json',
        'Cache-Control': 'no-cache',
        'AppID': app_id,
        'Version': app_Version,
        'Content-Type': 'application/json',
        'Host': 'api1.mimikko.cn',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'okhttp/3.12.1',
    }
    try:
        with requests.post(url, headers=headers, data=json.dumps(params), timeout=300) as resp:
            # logging.debug(resp.text)  # 请务必谨慎开启，因为包含 Authorization 参数！！！
            res = resp.json()
            return res
    except Exception as exl:
        logging.error(exl, exc_info=True)
        return False


def mimikko_get(url, app_id, app_Version, Authorization, params):      # 带尝试的get
    return_value = False
    i = 1
    while True:
        logging.debug(f"第{i}次尝试GET")
        return_value = mimikko_realGet(
            url, app_id, app_Version, Authorization, params)
        if return_value != False:
            logging.debug("SUCCESS")
            break
        if i == _MAX_TRIES:
            logging.warning(f"{_MAX_TRIES}次请求失败，已跳过")
            break
        i = i + 1

    return return_value


def mimikko_realGet(url, app_id, app_Version, Authorization, params):  # 实际get请求
    headers = {
        'Cache-Control': 'Cache-Control:public,no-cache',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'Mozilla/5.0(Linux;Android6.0.1;MuMu Build/V417IR;wv)AppleWebKit/537.36(KHTML,like Gecko)Version/4.0 Chrome/52.0.2743.100MobileSafari / 537.36',
        'AppID': app_id,
        'Version': app_Version,
        'Authorization': Authorization,
        'Host': 'api1.mimikko.cn'
    }
    try:
        with requests.get(url, headers=headers, params=params, timeout=300) as resp:
            logging.debug(resp.text)
            res = resp.json()
            return res
    except Exception as exg:
        logging.error(exg, exc_info=True)
        return False


def mimikko_post(url, app_id, app_Version, Authorization, params, content_type=False):      # 带尝试的post
    return_value = False
    i = 1
    if not content_type:
        content_type = 'application/json'
    logging.debug(
        f'{url}, {app_id}, {app_Version}, {Authorization}, {params}, {content_type}')
    while True:
        logging.debug(f"第{i}次尝试POST")
        return_value = mimikko_realPost(
            url, content_type, app_id, app_Version, Authorization, params)
        if return_value != False:
            logging.debug("SUCCESS")
            break
        if i == _MAX_TRIES:
            logging.warning(f"{_MAX_TRIES}次请求失败，已跳过")
            break
        i = i + 1

    return return_value


def mimikko_realPost(url, content_type, app_id, app_Version, Authorization, params):  # post请求
    headers = {
        'Accept': 'application/json',
        'Cache-Control': 'no-cache',
        'AppID': app_id,
        'Version': app_Version,
        'Authorization': Authorization,
        'Content-Type': content_type,
        'Host': 'api1.mimikko.cn',
        'Accept-Encoding': 'gzip',
        'User-Agent': 'okhttp/3.12.1',
    }
    try:
        with requests.post(url, headers=headers, data=params, timeout=300) as resp:
            logging.debug(resp.text)
            res = resp.json()
            return res
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return False


def timeStamp1time(timeStamp):  # 时间格式化1
    timeArray = time.localtime(timeStamp)
    StyleTime = time.strftime('%Y-%m-%d', timeArray)
    return StyleTime


def timeStamp2time(timeStamp):  # 时间格式化2
    timeArray = time.localtime(timeStamp)
    StyleTime = time.strftime('%Y年%m月%d日 %H:%M:%S', timeArray)
    return StyleTime


def ddpost(ding_token, ding_secret, title_post, post_text):  # 钉钉推送
    timestamp = str(round(time.time() * 1000))
    secret_enc = ding_secret.encode('utf-8')
    string_to_sign = f'{timestamp}\n{ding_secret}'
    string_to_sign_enc = string_to_sign.encode('utf-8')
    hmac_code = hmac.new(secret_enc, string_to_sign_enc,
                         digestmod=hashlib.sha256).digest()
    sign = urllib.parse.quote_plus(base64.b64encode(hmac_code))
    headers_post = {
        'Content-Type': 'application/json; charset=UTF-8',
    }
    url = f'https://oapi.dingtalk.com/robot/send?access_token={ding_token}&timestamp={timestamp}&sign={sign}'
    post_info = {
        "msgtype": "text",
        "text": {
            "content": f'{title_post}\n\n{post_text}'
        }
    }
    post_info = json.dumps(post_info)
    try:
        with requests.post(url, headers=headers_post, data=post_info, timeout=300) as post_data:
            logging.debug(post_data.text)
            if 'errcode' in post_data.json() and post_data.json()["errcode"] == 0:
                return post_data.json()["errcode"]
            else:
                return post_data.text
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def scpost(sckey, title_post, post_text):  # server酱推送
    headers_post = {
        'Content-Type': 'application/x-www-form-urlencoded',
    }
    post_info = {'text': title_post, 'desp': post_text}
    url = f'https://sctapi.ftqq.com/{sckey}.send'
    try:
        with requests.post(url, headers=headers_post, data=post_info, timeout=300) as post_data:
            logging.debug(post_data.text)
            if 'code' in post_data.json() and post_data.json()["code"] == 0:
                return post_data.json()["code"]
            else:
                return post_data.text
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def send2wechat(wx_agentid, wx_secret, wx_companyid, title_post, post_text):  # 企业微信推送
    """
    # 此段修改自https://www.jianshu.com/p/99f706f1e943
    :param AgentId: 应用ID
    :param Secret: 应用Secret
    :param CompanyId: 企业ID
    """
    # 通行密钥
    ACCESS_TOKEN = None
    ATurl = f'https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={wx_companyid}&corpsecret={wx_secret}'
    try:
        # 通过企业ID和应用Secret获取本地通行密钥
        with requests.get(ATurl, timeout=300) as r:
            logging.debug(r.text)
            r = r.json()
            ACCESS_TOKEN = r["access_token"]
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp
    # logging.debug(ACCESS_TOKEN)  # 注意账号安全
    # 要发送的信息格式
    data = {
        "touser": "@all",
        "msgtype": "text",
        "agentid": f"{wx_agentid}",
        "text": {"content": f'{title_post}\n\n{post_text}'}
    }
    # 字典转成json，不然会报错
    data = json.dumps(data)
    url = f'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={ACCESS_TOKEN}'
    try:
        if ACCESS_TOKEN:
            # 发送消息
            with requests.post(url, data=data, timeout=300) as post_data:
                logging.debug(post_data.text)
                if 'errcode' in post_data.json() and post_data.json()["errcode"] == 0:
                    return post_data.json()["errcode"]
                else:
                    return post_data.text
        else:
            return 'ACCESS_TOKEN获取失败，未发送'
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def dcpost(dc_webhook, title_post, post_text):  # Discord推送
    url = dc_webhook
    headers = {"Content-Type": "application/json"}
    data = {"content": f'{title_post}\n\n{post_text}'}
    try:
        # 发送消息
        with requests.post(url, headers=headers, data=json.dumps(data), timeout=300) as post_data:
            logging.debug(post_data.text)
            return post_data
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def tgpost(tg_token, tg_id, title_post, post_text):  # Telegram推送
    try:
        # 发送消息
        bot = telebot.TeleBot(tg_token)
        data = bot.send_message(tg_id, f'{title_post}\n\n{post_text}')
        return data.id
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def pppost(pp_token, title_post, post_text):  # PushPlus推送
    url = f'http://pushplus.hxtrip.com/send/{pp_token}'
    headers = {"Content-Type": "application/json"}
    data = {"title": title_post, "content": post_text}
    try:
        # 发送消息
        with requests.post(url, headers=headers, data=json.dumps(data), timeout=300) as post_data:
            logging.debug(post_data.text)
            if 'code' in post_data.json() and post_data.json()["code"] == 0:
                return post_data.json()["code"]
            else:
                return post_data.text
            return post_data
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def fspost(fs_token, fs_secret, title_post, post_text):  # 飞书推送
    timestamp = str(round(time.time()))
    secret = fs_secret
    key = f'{timestamp}\n{secret}'
    key_enc = key.encode('utf-8')
    msg = ""
    msg_enc = msg.encode('utf-8')
    hmac_code = hmac.new(key_enc, msg_enc, digestmod=hashlib.sha256).digest()
    sign = base64.b64encode(hmac_code).decode('utf-8')
    print(timestamp)
    print(sign)
    headers_post = {
        'Content-Type': 'application/json; charset=UTF-8',
    }
    url = f'https://open.feishu.cn/open-apis/bot/v2/hook/{fs_token}'
    post_info = {
        "timestamp": timestamp,
        "sign": sign,
        "msg_type": "text",
        "content": {
            "text": f'{title_post}\n\n{post_text}'
        }
    }
    post_info = json.dumps(post_info)
    try:
        with requests.post(url, headers=headers_post, data=post_info, timeout=300) as post_data:
            logging.debug(post_data.text)
            if 'StatusCode' in post_data.json() and post_data.json()["StatusCode"] == 0:
                return post_data.json()["StatusCode"]
            else:
                return post_data.text
    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def misakapost(misaka_position, misaka_key, title_post, post_text):  # MisakaNet推送
    headers_post = {
        "misaka-key": misaka_key
    }
    try:
        with requests.post(misaka_position, headers=headers_post, data=f'{title_post}\n\n{post_text}'.encode('utf-8'), timeout=300) as post_data:
            logging.debug(post_data)
            return post_data.json()

    except Exception as exp:
        logging.error(exp, exc_info=True)
        return exp


def AllPush(ding_token, ding_secret, wx_agentid, wx_secret, wx_companyid, sckey, dc_webhook, tg_token, tg_id, pp_token, fs_token, fs_secret, misaka_position, misaka_key, title_post, post_text):  # 全推送
    dddata = scdata = wxdata = dcdata = tgdata = ppdata = fsdata = misakadata = False
    if sckey:
        logging.info("正在推送到Server酱")
        scdata = scpost(sckey, title_post, post_text)  # server酱推送
    else:
        logging.info('sckey不存在')
    if ding_token and ding_secret:
        logging.info("正在推送到钉钉")
        dddata = ddpost(ding_token, ding_secret, title_post, post_text)  # 钉钉推送
    else:
        logging.info('ding_token或ding_secret不存在')
    if wx_agentid and wx_secret and wx_companyid:
        logging.info("正在推送到企业微信")
        wxdata = send2wechat(wx_agentid, wx_secret, wx_companyid,
                             title_post, post_text)  # 企业微信推送
    else:
        logging.info('wx_agentid, wx_secret或wx_companyid不存在')
    if dc_webhook:
        logging.info("正在推送到Discord")
        dcdata = dcpost(dc_webhook, title_post, post_text)  # Discord推送
    else:
        logging.info('dc_webhook不存在')
    if tg_token and tg_id:
        logging.info("正在推送到Telegram")
        tgdata = tgpost(tg_token, tg_id, title_post, post_text)  # Telegram推送
    else:
        logging.info('tg_token或tg_id不存在')
    if pp_token:
        logging.info("正在推送到PushPlus")
        ppdata = pppost(pp_token, title_post, post_text)  # PushPlus推送
    else:
        logging.info('pp_token不存在')
    if fs_token and fs_secret:
        logging.info("正在推送到飞书")
        fsdata = pppost(pp_token, title_post, post_text)  # 飞书推送
    else:
        logging.info('fs_token或fs_secret不存在')
    if misaka_position and misaka_key:
        logging.info("正在推送到misakaNet")
        misakadata = misakapost(
            misaka_position, misaka_key, title_post, post_text)
    else:
        logging.info("misaka_position或misaka_key不存在")
    return dddata, scdata, wxdata, dcdata, tgdata, ppdata, fsdata, misakadata


def push_check(push_set1, push_set2, push_set3, push_set4, push_set5, push_set6, push_set7, push_set8, dddata, scdata, wxdata, dcdata, tgdata, ppdata, fsdata, misakadata):
    if push_set1:
        if str(scdata) == '0':
            logging.info(f'server酱 errcode: {scdata}')
        else:
            logging.warning(f'server酱 error: {scdata}')
    if push_set2:
        if str(dddata) == '0':
            logging.info(f'钉钉 errcode: {dddata}')
        else:
            logging.warning(f'钉钉 error: {dddata}')
    if push_set3:
        if str(wxdata) == '0':
            logging.info(f'企业微信 errcode: {wxdata}')
        else:
            logging.warning(f'企业微信 error: {wxdata}')
    if push_set4:
        if not str(dcdata) == 'False':
            logging.info(f'Discord: {dcdata}')
        else:
            logging.warning(f'Discord error: {dcdata}')
    if push_set5:
        if ppdata == 200:
            logging.info(f'PushPlus errcode: {ppdata}')
        else:
            logging.warning(f'PushPlus error: {ppdata}')
    if push_set6:
        if str(fsdata) == '0':
            logging.info(f'飞书 errcode: {fsdata}')
        else:
            logging.warning(f'飞书 error: {fsdata}')
    if push_set7:
        if type(tgdata) == int:
            logging.info(f'Telegram msgcode: {tgdata}')
        else:
            logging.warning(f'Telegram error: {tgdata}')
    if push_set8:
        if misakadata["OK"]:
            logging.info("MisakaNet done")
        else:
            logging.info(f"MisakaNet error: {misakadata['error']}")


def push_set_check(push_set1, push_set2, push_set3, push_set4, push_set5, push_set6, push_set7, push_set8, dddata, scdata, wxdata, dcdata, tgdata, ppdata, fsdata, misakadata):
    if push_set1 and str(scdata) == '0':
        push_set1 = False
    if push_set2 and str(dddata) == '0':
        push_set2 = False
    if push_set3 and str(wxdata) == '0':
        push_set3 = False
    if push_set4 and not str(dcdata) == 'False':
        push_set4 = False
    if push_set5 and ppdata == 200:
        push_set5 = False
    if push_set6 and str(fsdata) == '0':
        push_set6 = False
    if push_set7 and type(tgdata) == int:
        push_set7 = False
    if push_set8 and misakadata["OK"]:
        push_set8 = False
    return push_set1, push_set2, push_set3, push_set4, push_set5, push_set6, push_set7, push_set8
